package biolabs.sink;

import java.awt.image.RenderedImage;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.imageio.ImageIO;

import biolabs.core.Application$;

public class ImageSequenceSink implements Sink<RenderedImage> {

	private static final Logger LOGGER = Application$.MODULE$.LOGGER();

	private final File outputDir;
	private final String filePrefix;
	private final String numberFmt;

	public ImageSequenceSink(File outputDir, String filePrefix, int zeroPadWidth) throws IOException {

		if(filePrefix.indexOf('/') != -1)
			throw new IllegalArgumentException("Filename prefix cannot contain a slash ('/')");

		if(zeroPadWidth < 0)
			throw new IllegalArgumentException("zeroPadWidth cannot be negative");

		outputDir = outputDir.getAbsoluteFile();
		outputDir.mkdirs();

		if(!outputDir.exists())
			throw new IOException("Directory " + outputDir + " does not exist and could not be created");
		if(!outputDir.isDirectory())
			throw new IOException("File " + outputDir + " exists and is not a directory");
		if(!outputDir.canWrite())
			throw new IOException(outputDir + " is not writable by the application");

		this.outputDir = outputDir;
		this.filePrefix = filePrefix;
		this.numberFmt = "%0" + zeroPadWidth + "d";
	}

	public ImageSequenceSink(String outputDir, String filePrefix, int zeroPadWidth) throws IOException {
		this(new File(outputDir), filePrefix, zeroPadWidth);
	}

	public ImageSequenceSink(File outputDir) throws IOException {
		this(outputDir, "", 4);
	}

	public ImageSequenceSink(String outputDir) throws IOException {
		this(new File(outputDir));
	}

	@Override
	public void close() {
		// do nothing
	}

	@Override
	public void flush() {
		// do nothing
	}

	@Override
	public void push(long time, RenderedImage image) {
		String outName = filePrefix + String.format(numberFmt, time) + ".png";
		File outFile = new File(outputDir, outName);
		try {
			ImageIO.write(image, "png", outFile);
		} catch (IOException e) {
			LOGGER.log(Level.SEVERE, "Failed to write an image", e);
		}
	}

}
